-- fastdissect.lua - example wireshark dissector for EAP-FAST over udp
-- this example is based on tutorial by Stig Bj?rlykke.
-- for more information on how to write dissectors, post dissectors, and listeners see
-- http://www.cacetech.com/sharkfest.09/DT06_Bjorlykke_Lua%20Scripting%20in%20Wireshark.pdf

do
    require "bitstring"

    -- create the dissector
    local fastudp = Proto("fastudp", "Example for EAP-FAST over UDP dissector")

    -- here we place one time initialization code
    function fastudp.init()
    end

    -- field definitions for our protocol that tell
    -- wireshark how to parse and display chunks of data
    local f = fastudp.fields
    f.code = ProtoField.uint8("fastudp.code", "code")
    f.identifier = ProtoField.uint8("fastudp.identifier", "identifier")
    f.length = ProtoField.uint16("fastudp.length", "length")
    f.eap_type = ProtoField.uint8("fastudp.eap_type", "eap type")
    f.lflag = ProtoField.uint8("fastudp.lflag", "lflag", base.HEX, nil, 0x80)
    f.mflag = ProtoField.uint8("fastudp.mflag", "mflag", base.HEX, nil, 0x40)
    f.sflag = ProtoField.uint8("fastudp.sflag", "sflag", base.HEX, nil, 0x20)
    f.rflag = ProtoField.uint8("fastudp.rflag", "rflag", base.HEX, nil, 0x18)
    f.version = ProtoField.uint8("fastudp.version", "version", base.HEX, nil, 0x07)
    f.fast_length = ProtoField.uint32("fastudp.fast_length", "eap-fast length")
    f.data = ProtoField.bytes("fastudp.data", "eap-fast data")

    -- the dissector function is called for each captured packet
    -- for protocol that we subscribed 
    function fastudp.dissector(buffer, pinfo, tree)
        -- Adding fields to the tree
        local subtree = tree:add(fastudp, buffer())
        local offset = 0
        -- find the chunk of buffer that holds the code
        local code = buffer(offset, 1)
        -- add the code field to subtree
        -- using field definition from above
        subtree:add(f.code, code)
        local identifier = buffer(offset + 1, 1)
        subtree:add(f.identifier, identifier)
        local length = buffer(offset + 2, 2)
        subtree:add(f.length, length)
        local eap_type = buffer(offset + 4, 1)
        subtree:add(f.eap_type, eap_type)

        local flags = buffer(offset + 5, 1)
        subtree:add(f.lflag, flags)
        subtree:add(f.mflag, flags)
        subtree:add(f.sflag, flags)
        subtree:add(f.rflag, flags)
        subtree:add(f.version, flags)

        -- get flags bit values 
        local lflag, mflag, sflag, rflags, version = 
        bitstring.unpack("1:int, 1:int, 1:int, 2:int, 3:int", 
        bitstring.fromhexstream(tostring(flags:bytes())))

        -- if length flag is set add length field
        -- to subtree
        if lflag == 1 then
            local fast_length = buffer(offset + 6, 4)
            subtree:add(f.fast_length, fast_length)
        end

        local data = buffer(offset + 10)
        subtree:add(f.data, data)
    end

    -- subscribe for UDP packets on port 1818
    local udp_table = DissectorTable.get("udp.port")
    udp_table:add(1818, fastudp)
end
